require 'helper_common'
require 'helper_watir'
require 'helper_autoit'
require 'testcase'
require 'value_processor'

module LWA
  class Engine

    attr_reader :test_case
    attr_accessor :close_browser_when_finished

    def initialize
      @auto_hash = Hash.new
      @value_processor = ValueProcessor.new("..\\lib\\value_storage.yaml")
    end

    def process_single_step(one_step)
      begin
        automator = set_automator(one_step.by)
        automator.send(one_step.command, @value_processor.get_value(one_step.target), @value_processor.get_value(one_step.value))
      rescue => error
        raise RuntimeError, "In step #{one_step.id}, #{error.to_s}", caller
      end
    end

    def process_condition_step(step)
      condition = true
      begin
        process_single_step(step)
      rescue => err
        puts "INFO: Condition failed as #{err.message}"
        condition = false
      ensure
        return condition
      end
    end

    def process_testcase(obj_testcase)
      step = nil
      steps = load_testcase(obj_testcase).step_list
      begin
        steps.each do |step_x|
          step = step_x
          case step_x.class.to_s
          when /LWA::Step/
            process_single_step(step_x)
          when /LWA::Snippet/
            step_x.steps.each {|snippet_step| steps.insert(steps.index(step_x)+1, snippet_step); step_x = snippet_step }
          when /LWA::Conditional/
            if process_condition_step(step_x.condition_step)
              step_x.content_steps.each {|content_step| steps.insert(steps.index(step_x)+1, content_step); step_x = content_step }
            end
          end
        end
      rescue => err
        puts "ERROR: In step #{step.id}, #{err}"
        raise err
      ensure
        @auto_hash.clear
        kill_process("iexplore.exe") if @close_browser_when_finished
      end
    end

    private

    def set_automator(automator)
      class_name, instance_name, init_parameter = automator.split(".")
      key = (instance_name == nil) ? class_name : class_name + instance_name
      if @auto_hash.has_key?(key)
        @auto_hash[key]
      else
        autor = Object.const_get(class_name).new(init_parameter)
        @auto_hash.store(key, autor)
        return autor
      end
    end

    def load_testcase(obj_testcase)
      @test_case = obj_testcase
    end
  end
end